package com.cw.jeeyt.service.impl.process;

import java.util.Date;
import java.util.List;

import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cw.jeeyt.common.Order;
import com.cw.jeeyt.common.utils.StringUtils;
import com.cw.jeeyt.service.bo.process.ActDeModelBo;
import com.cw.jeeyt.service.bo.security.SecurityUserBo;
import com.cw.jeeyt.core.util.SessionUtil;
import com.cw.jeeyt.dao.intf.process.ActDeModelDao;
import com.cw.jeeyt.dao.model.process.ActDeModelDo;
import com.cw.jeeyt.service.converter.process.ActDeModelConverter;
import com.cw.jeeyt.service.intf.process.ActDeModelService;
import com.cw.lang.mybatis.dto.PageInfo;
import com.cw.lang.common.utils.SequenceTool;

/**
 * 流程定义模型业务实现类
 *
 * @author chenw
 * @date 2019-03-10 21:47:04
 */
@Service
public class ActDeModelServiceImpl implements ActDeModelService {

    private static final Logger logger = LoggerFactory.getLogger(ActDeModelServiceImpl.class);
    //流程定义模型数据库操作接口
    @Autowired
    private ActDeModelDao actDeModelDao;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ModelService modelService;
    /**
     * 查询所有流程定义模型
     */
    @Override
    public List<ActDeModelBo> queryActDeModelList() throws Exception {
        return ActDeModelConverter.doList2BoList(actDeModelDao.queryActDeModelList());
    }

    /**
     * 分页查询流程定义模型
     *
     * @param actDeModelBo
     * @param startNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public PageInfo<ActDeModelBo> queryByPage(ActDeModelBo actDeModelBo, Integer startNum, Integer pageSize,
        Order order) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return null;
        }
        PageInfo<ActDeModelDo> pageInfo = actDeModelDao.queryByPage(ActDeModelConverter.bo2Do(actDeModelBo), startNum,
            pageSize, order);
        return new PageInfo<>(pageInfo, ActDeModelConverter.doList2BoList(pageInfo.getList()));
    }

    /**
     * 根据主键查询流程定义模型信息
     *
     * @return
     */
    @Override
    public ActDeModelBo getActDeModelById(String id) throws Exception {

        if (StringUtils.isEmpty(id)) {
            logger.error("--主键id为空--");
            return null;
        }
        return ActDeModelConverter.do2Bo(actDeModelDao.getById(id));
    }

    /**
     * 新增流程定义模型
     *
     * @param actDeModelBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer insert(ActDeModelBo actDeModelBo) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return null;
        }
        SecurityUserBo userBo = SessionUtil.getSessionUser();
        if (userBo == null) {
            logger.error("用户未登录");
            throw new Exception("用户未登录");
        }
        ActDeModelDo actDeModel = ActDeModelConverter.bo2Do(actDeModelBo);
        actDeModel.setId(SequenceTool.nextId());
        actDeModel.setCreatedBy(userBo.getId()
            .toString());
        actDeModel.setCreated(new Date());
        actDeModel.setLastUpdatedBy(userBo.getId()
            .toString());
        actDeModel.setLastUpdated(new Date());
        Integer result = actDeModelDao.insert(actDeModel);
        return result;
    }

    /**
     * 新增流程定义模型不为空的字段
     *
     * @param actDeModelBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer insertSelective(ActDeModelBo actDeModelBo) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return null;
        }
        SecurityUserBo userBo = SessionUtil.getSessionUser();
        if (userBo == null) {
            logger.error("用户未登录");
            throw new Exception("用户未登录");
        }
        ActDeModelDo actDeModel = ActDeModelConverter.bo2Do(actDeModelBo);
        actDeModel.setId(SequenceTool.nextId());
        actDeModel.setCreatedBy(userBo.getId()
            .toString());
        actDeModel.setCreated(new Date());
        actDeModel.setLastUpdatedBy(userBo.getId()
            .toString());
        actDeModel.setLastUpdated(new Date());
        Integer result = actDeModelDao.insertSelective(actDeModel);
        return result;
    }

    /**
     * 更新流程定义模型
     *
     * @param actDeModelBo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(ActDeModelBo actDeModelBo) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return;
        }
        SecurityUserBo userBo = SessionUtil.getSessionUser();
        if (userBo == null) {
            logger.error("用户未登录");
            throw new Exception("用户未登录");
        }
        ActDeModelDo actDeModel = ActDeModelConverter.bo2Do(actDeModelBo);
        actDeModel.setLastUpdatedBy(userBo.getId()
            .toString());
        actDeModel.setLastUpdated(new Date());

        actDeModelDao.update(actDeModel);
    }

    /**
     * 更新流程定义模型不为空的字段
     *
     * @param actDeModelBo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateSelective(ActDeModelBo actDeModelBo) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return;
        }
        SecurityUserBo userBo = SessionUtil.getSessionUser();
        if (userBo == null) {
            logger.error("用户未登录");
            throw new Exception("用户未登录");
        }
        ActDeModelDo actDeModel = ActDeModelConverter.bo2Do(actDeModelBo);
        actDeModel.setLastUpdatedBy(userBo.getId()
            .toString());
        actDeModel.setLastUpdated(new Date());

        actDeModelDao.updateSelective(actDeModel);
    }

    /**
     * 删除流程定义模型
     *
     * @param actDeModelBo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(ActDeModelBo actDeModelBo) throws Exception {

        if (actDeModelBo == null) {
            logger.error("流程定义模型为空");
            return;
        }
        ActDeModelDo actDeModel = ActDeModelConverter.bo2Do(actDeModelBo);
        actDeModelDao.delete(actDeModel);
    }

    /**
     * 流程定义部署
     *
     * @param modelId
     * @param category
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public String doDeploy(String modelId, String category) {

        String message = "";

        org.flowable.ui.modeler.domain.Model model = modelService
            .getModel(modelId);
        byte[] bpmnBytes = modelService.getBpmnXML(model);

        String processName = model.getName();
        if (!StringUtils.endsWith(processName, ".bpmn20.xml")) {
            processName += ".bpmn20.xml";
        }

        Deployment deployment = repositoryService.createDeployment()
            .addBytes(processName, bpmnBytes)
            .name(model.getName())
            .key(model.getKey())
            .deploy();

        logger.debug("流程部署--------deploy：" + deployment + "  分类---------->" + category);

        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
            .deploymentId(deployment.getId())
            .list();

        // 设置流程分类
        for (ProcessDefinition processDefinition : list) {
            if (StringUtils.isNotBlank(category)) {
                repositoryService.setProcessDefinitionCategory(processDefinition.getId(), category);
            }
            message += "部署成功，流程ID=" + processDefinition.getId() + "<br/>";
        }

        if (list.size() == 0) {
            message = "部署失败，没有流程。";
        }

        return message;
    }

    @Override
    public PageInfo<ActDeModelBo> findPage(PageInfo<ActDeModelBo> actDeModelBoPageInfo, ActDeModelBo deModel) {
        return null;
    }
}
